package com.repro.libstate

import android.animation.ValueAnimator
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import com.repro.libstate.state.LoadingState
import com.repro.libstate.state.SuccessState

/**
 * MultiState核心类
 * 展示界面，缓存数据，执行动画
 */
class MultiStateContainer : FrameLayout {
    //根布局
    private var mContentsView: View? = null

    //缓存MultiState
    private var statePool: MutableMap<Class<out MultiState>, MultiState> = mutableMapOf()
    private var lastState: String = ""

    //属性动画这里只是界面展示动画 从透明变到不透明
    private var animator = ValueAnimator.ofFloat(0.0f, 1.0f).apply {
        duration = 500
    }

    var onRetryEventListener: OnRetryEventListener? = null


    constructor(
        context: Context,
        mContentsView: View,
        onRetryEventListener: OnRetryEventListener? = null
    ) : this(context, null) {
        this.mContentsView = mContentsView
        this.onRetryEventListener = onRetryEventListener
    }


    //实例
    constructor(context: Context) : super(context)
    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
        context,
        attrs,
        defStyleAttr
    )

    /**
     * 当我们的XML布局被加载完后，就会回调onFinishInflate这个方法，在这个方法中我们可以初始化控件和数据。
     * init初始化方法
     */
    override fun onFinishInflate() {
        super.onFinishInflate()
        if (mContentsView == null && childCount == 1) {
            mContentsView = getChildAt(0)//获取获取原始布局
        }
    }

    /**
     * stateView 添加到本View
     */
    fun initialization() {
        val layoutParams = ViewGroup.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.MATCH_PARENT
        )
        addView(mContentsView, 0, layoutParams)//讲原始布局添加到multiStateContainer中
    }


    inline fun <reified T : MultiState> show(
        enableAnimator: Boolean = true,
        noinline notify: (T) -> Unit = {}
    ) {
        show(T::class.java, enableAnimator, notify)
    }

    /**
     * 获取state布局，先从缓存取如果缓存里面有则返回缓存缓存没有则重新创建。
     */
    @Suppress("UNCHECKED_CAST")
    @JvmOverloads
    fun <T : MultiState> show(
        clazz: Class<T>,
        enableAnimator: Boolean = true,
        onNotifyListener: OnNotifyListener<T>? = null
    ) {
        findState(clazz)?.let { multiState ->
            show(multiState as T , enableAnimator, onNotifyListener)
        }
    }


    fun <T : MultiState> show(
        multiState: T,
        enableAnimator: Boolean = true,
        onNotifyListener: OnNotifyListener<T>? = null
    ) {
        if (childCount == 0) {
            initialization()
        }

        //已经删除掉已经添加的stateView
        if (childCount > 1) {//防止多次添加之所以是2是为了防止
            removeViewAt(1)//
        }

        if (multiState is SuccessState) {
            //如果上一次暂时的是成功状态,则展示成功状态界面重新执行下动画即可
            if (lastState != SuccessState::class.java.name) {
                mContentsView?.visibility = VISIBLE//显示原始布局
                if (enableAnimator) mContentsView?.executeAnimator()
            }
        } else {//如果不是成功状态,
            if (multiState !is LoadingState) {//只要不是loading状态则隐藏原始布局
                mContentsView?.visibility = INVISIBLE//则隐藏原始布局
            }
            val currentStateView = multiState.onCreateMultiStateView(
                context,
                LayoutInflater.from(context),
                this
            )//创建stateview
            multiState.onMultiStateViewCreate(currentStateView)//创建完成
            if (multiState.enableReload()) {
                val retryView = multiState.bindRetryView()//绑定重试点击按钮
                if (retryView != null) {
                    retryView.setOnClickListener { onRetryEventListener?.onRetryEvent(this) }
                } else {
                    currentStateView.setOnClickListener { onRetryEventListener?.onRetryEvent(this) }
                }
            }
            addView(currentStateView)
            if (enableAnimator) {
                currentStateView.executeAnimator()
            }
            onNotifyListener?.onNotify(multiState)
        }
        //记录上展示的state
        lastState = multiState.javaClass.name
    }


    /**
     * state缓存，没有缓存添加缓存有缓存则从缓存里面取
     * 减少重复创建节约空间
     */
    private fun <T : MultiState> findState(clazz: Class<T>): MultiState? {
        return if (statePool.containsKey(clazz)) {
            statePool[clazz]
        } else {
            val state = clazz.newInstance()
            statePool[clazz] = state
            state
        }
    }

    /**
     * View.执行动画
     */
    private fun View.executeAnimator() {
        this.clearAnimation()//清理掉已经存在的动画
        animator.addUpdateListener {
            this.alpha = it.animatedValue as Float
        }
        animator.start()
    }

}